from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
import logging
import simplejson
import _base
from google.appengine.ext import db
import datetime

# All Configs
PROTOCOL_VERSION = 1
DEVICE_TYPE_ANDROID = "android"
DEVICE_TYPE_IPHONE = "iphone"

class MainPage(webapp.RequestHandler):
    
    def post(self):
        self.error(403) # under construction: access denied
    
    def get(self):
        print 'hello'
    
# Model API    
class Timestamped(db.Model):
    def getCreatedDate(self):
        pass
    def getModifiedDate(self):
        pass

class Syncable(Timestamped):
    def isPendingDelete(self):
        pass

class Note(Syncable):
    ownerKey = db.ReferenceProperty()
    title = db.StringProperty()
    body = db.StringProperty()
    createdDate = db.DateTimeProperty(auto_now=True)
    modifiedDate = db.DateTimeProperty()
    pendingDelete = db.BooleanProperty()
    localId = db.StringProperty()

    def fromJson(self, json):
        if not json:
            return;
        pass
    
    def __init__(self, json):
        Syncable.__init__(self)
        self.createdDate = datetime.datetime.now().date()
        self.modifiedDate = datetime.datetime.now().date()
        self.fromJSON(json);

    def touch(self):
        self.modifiedDate = datetime.datetime.now().date()
        
    def getId(self):
        pass
    def getOwnerId(self):
        pass
    def getTitle(self):
        pass
    def setTitle(self, title):
        pass
    def getBody(self):
        pass
    def setBody(self, body):
        pass

class UserInfo(db.Model):
    def getId(self):
        pass
    def getEmail(self):
        pass

class DeviceRegistration(db.Model):
    def getDeviceId(self):
        pass
    def getOwnerId(self):
        pass
    def getDeviceType(self):
        pass
    def getRegistrationToken(self):
        pass
    def setRegistrationToken(self, registrationToken):
        pass
    
# =============================================================================
class CallContext:
    request = None
    params = None

    def __init__(self, request, params):
        self.request = request
        self.params = params

    def getRequest(self):
        return self.request
    
    def getParams(self):
        return self.params

    def setParams(self, params):
        self.params = params
        
        
class JsonRpcError(Exception):
    """
        JsonRpc exception class to capture details on a json error:
    """
    httpCode = 200
    methodName = None
    
    def __init__(self, httpCode, txt):
        Exception.__init__(self, txt)
        self.httpCode = httpCode
        self.message = txt
        
    def getHttpCode(self):
        return self.httpCode

    def getMethodName(self):
        return self.methodName

    def setMethodName(self, methodName):
        self.methodName = methodName;
    
    def getMessage(self):
        return self.message
    
        
class JsonRpcHandler(webapp.RequestHandler):
    def __init__(self):
        webapp.RequestHandler.__init__(self)
        logging.info('JsonRpcHandler __init__()') 

    def get(self):
        self.error(403) # under construction: access denied
                 
    def post(self):
        logging.info('JsonRpcHandler.post()') 
        prettyPrint = False
        requestJson = None
        callsJson = None
        responseJson = {}
        resultsJson = []
        context = CallContext(self, None)

        jsonEntity = self.request.get('json')
        logging.info('passed JsonRpcHandler.post()::jsonEntity') 
        if jsonEntity:
            requestJson = simplejson.loads(jsonEntity)
            if requestJson:
                try:
                    if requestJson.has_key('pretty'):
                        prettyPrint = bool(requestJson['pretty'])
                except KeyError:
                    prettyPrint = False
                callsJson = requestJson['calls']
            else:
                responseJson['error'] = 400
                responseJson['message'] = 'Error parsing request object: (requestJson = simplejson.loads(jsonEntity))'
        else:
            self.error(500)
            self.response.headers['Content-Type'] = 'text/plain'
            self.response.out.write('Internal JSON serialization error: jsonEntity is None')
            return;

        if callsJson:
            for callParamsJson in callsJson:
                resultJson = {}
                context.setParams(callParamsJson)
                try:
                    dataJson = self.performCall(context)
                    if dataJson:
                        resultJson['data'] = dataJson
                    else:
                        resultJson['error'] = 500
                        resultJson['message'] = 'Internal error: dataJson is None'
                except JsonRpcError, e:
                    resultJson['error'] = e.getHttpCode()
                    resultJson['message'] = 'Internal error: ' + e.getMessage()
                resultsJson.append(resultJson)
        responseJson['results'] = resultsJson
        
        self.response.headers['Content-Type'] = 'application/json'
        if prettyPrint: # need to 2 intent+
            self.response.out.write(responseJson)
        else:
            self.response.out.write(responseJson)
            
    def performCall(self, context):
        if not context.getParams().has_key('method'):
            raise JsonRpcError(400, 'No method specified.')
        func = None
        try:
            methodName = context.getParams()['method']
            func = getattr(self, 'rpc_' + methodName, None)
            if func:
                func(methodName, context)
            else:
                raise JsonRpcError(400, 'invalid method.')
        except KeyError:
            raise JsonRpcError(400, 'unknown method.')

class DateNoteHandler(JsonRpcHandler):
    
    def trace(self, methodName, context):
        callParamsJson = context.getParams()
        logging.info('%s %s' % (methodName, str(callParamsJson)))
        
    # RPC API
    def rpc_notes_sync(self, methodName, context):
        self.trace(methodName, context)
        dataJson = {}
        return dataJson
        
    def rpc_user_info(self, methodName, context):
        self.trace(methodName, context)
        dataJson = {}
        return dataJson
   
    def rpc_server_info(self, methodName, context):
        self.trace(methodName, context)
        dataJson = {}
        dataJson['protocol_version'] = PROTOCOL_VERSION
        return dataJson
    
    def rpc_notes_list(self, methodName, context):
        self.trace(methodName, context)
        dataJson = {}
        return dataJson        

    def rpc_notes_get(self, methodName, context):
        self.trace(methodName, context)
        dataJson = {}
        return dataJson
                
    def rpc_notes_create(self, methodName, context):
        self.trace(methodName, context)
        dataJson = {}
        return dataJson
            
    def rpc_notes_edit(self, methodName, context):
        self.trace(methodName, context)
        dataJson = {}
        return dataJson
            
    def rpc_notes_delete(self, methodName, context):
        self.trace(methodName, context)
        dataJson = {}
        return dataJson
            
    def rpc_devices_register(self, methodName, context):
        self.trace(methodName, context)
        dataJson = {}
        return dataJson
            
    def rpc_devices_unregister(self, methodName, context):
        self.trace(methodName, context)
        dataJson = {}
        return dataJson
            
    def rpc_devices_clear(self, methodName, context):
        self.trace(methodName, context)
        dataJson = {}
        return dataJson
   
    def getCurrentUserInfo(self, context):
        pass
    
    def enqueueDeviceMessage(self, userInfo, clientDeviceId):
        pass


application = webapp.WSGIApplication([('/', MainPage),
                                      ('/datenoterpc', DateNoteHandler),
                                      ], debug=True)


def main():
    run_wsgi_app(application)


if __name__ == "__main__":
    main()
